package com.lanyou.esb.cook.proxy.redis.proxy.base;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
import redis.clients.jedis.exceptions.JedisException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.lanyou.esb.cook.proxy.redis.JedisPoolUtils;
import com.lanyou.esb.cook.proxy.redis.proxy.ListJedisProxy;

/**
 * List数据类型,操作Redis代理类基类
 * 
 * @author Davey.wu
 */
public abstract class BaseListJedisProxy<T> extends BaseJedisProxy<T> implements
		ListJedisProxy<T> {
	@Override
	public String getKeyFromObject(T t) {
		return getKey();
	}

	@Override
	public void rpush(List<T> list) throws JedisException,
			JsonProcessingException {
		if (list == null || list.isEmpty()) {
			return;
		}
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return;
		}
		boolean broken = false;
		try {
			// TODO 是否需要先清空相关数据
			Pipeline p = jedis.pipelined();
			for (T t : list) {
				p.rpush(this.getKey(), this.toJson(t));
			}
			p.sync();
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
	}

	@Override
	public void lpush(String key, T t) throws JedisException,
			JsonProcessingException {
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return;
		}
		String json = this.toJson(t);
		boolean broken = false;
		try {
			jedis.lpush(key, json);
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
	}

	@Override
	public void lpush(Jedis jedis, String key, T t) throws JedisException,
			JsonProcessingException {
		// add to redis
		jedis.lpush(key, this.toJson(t));
	}

	@Override
	public void rpush(String key, T t) throws JedisException,
			JsonProcessingException {
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return;
		}
		String json = this.toJson(t);
		boolean broken = false;
		try {
			jedis.rpush(key, json);
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
	}

	@Override
	public T lpop(String key) throws JedisException, JsonParseException,
			JsonMappingException, IOException {
		T result = null;
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return null;
		}
		boolean broken = false;
		try {
			result = listLeftPop(jedis, key);
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
		return result;
	}

	@Override
	public List<T> lpop(String key, int m) throws JedisException,
			JsonParseException, JsonMappingException, IOException {
		List<T> result = null;
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return null;
		}
		boolean broken = false;
		List<Response<String>> responses = new ArrayList<>(m);
		try {
			Pipeline pipe = jedis.pipelined();
			for (int i = 0; i < m; ++i) {
				responses.add(pipe.lpop(key));
			}
			pipe.sync();
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
		if (responses.isEmpty()) {
			return null;
		}
		result = new ArrayList<>(responses.size());
		try {
			for (Response<String> response : responses) {
				String value = response.get();
				if (StringUtils.isBlank(value)) {
					continue;
				}
				// 将JSON字符串转换成JAVA对象
				result.add(fromJson(value));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	public List<String> lpopAsStr(String key, int m) throws JedisException,
			JsonParseException, JsonMappingException, IOException {
		List<String> result = null;
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return null;
		}
		boolean broken = false;
		List<Response<String>> responses = new ArrayList<>(m);
		try {
			Pipeline pipe = jedis.pipelined();
			for (int i = 0; i < m; ++i) {
				responses.add(pipe.lpop(key));
			}
			pipe.sync();
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
		if (responses.isEmpty()) {
			return null;
		}
		result = new ArrayList<>(responses.size());
		for (Response<String> response : responses) {
			String value = response.get();
			if (StringUtils.isBlank(value)) {
				continue;
			}
			result.add(value);
		}
		return result;
	}

	@Override
	public T lpop(Jedis jedis, String key) throws JedisException,
			JsonParseException, JsonMappingException, IOException {
		// TODO Auto-generated method stub
		return listLeftPop(jedis, key);
	}

	@Override
	public T rpop(String key) throws JedisException, JsonParseException,
			JsonMappingException, IOException {
		T result = null;
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return null;
		}
		boolean broken = false;
		try {
			result = listRightPop(jedis, key);
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
		return result;
	}

	@Override
	public T rpop(Jedis jedis, String key) throws JedisException,
			JsonParseException, JsonMappingException, IOException {
		// TODO Auto-generated method stub
		return listRightPop(jedis, key);
	}

	/**
	 * 从链表左侧取出一个元素
	 * 
	 * @param jedis
	 * @param key
	 * @return
	 * @throws IOException
	 * @throws JsonMappingException
	 * @throws JsonParseException
	 */
	private T listLeftPop(Jedis jedis, String key) throws JedisException,
			JsonParseException, JsonMappingException, IOException {
		T target = null;
		// 从左边获取一个元素
		String value = jedis.lpop(key);
		// 将JSON字符串转换成JAVA对象
		if (target == null && StringUtils.isNotBlank(value)) {
			target = fromJson(value);
		}
		return target;
	}

	/**
	 * 从链表右侧取出一个元素
	 * 
	 * @param jedis
	 * @param key
	 * @param database
	 * @return
	 * @throws IOException
	 * @throws JsonMappingException
	 * @throws JsonParseException
	 */
	private T listRightPop(Jedis jedis, String key) throws JedisException,
			JsonParseException, JsonMappingException, IOException {
		T target = null;
		String value = jedis.rpop(this.getKey());
		// 将JSON字符串转换成JAVA对象
		if (target == null && StringUtils.isNotBlank(value)) {
			target = fromJson(value);
		}
		return target;
	}
}
